/*==========================================================================
 * 
 * GotoDialog.java
 * 
 * $Author: randallco $
 * $Revision: 1.3 $
 * $Date: 2008/05/04 16:06:54 $
 * $Name:  $
 * 
 * Created on 2-Feb-2004
 * Created by Marcel Palko alias Randallco (randallco@users.sourceforge.net)
 *==========================================================================*/
package net.sourceforge.ehep.gui;

import org.eclipse.swt.*;
import org.eclipse.swt.widgets.*;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.events.FocusEvent;
import org.eclipse.swt.events.FocusListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.jface.dialogs.MessageDialog;

import net.sourceforge.ehep.core.EHEP;

/**
 * @author Marcel Palko
 * @author randallco@users.sourceforge.net
 */
public class GotoDialog extends Dialog {
	private Shell dialog;
	private Button btnDecAddress;
	private Button btnHexAddress;
	private Text txtAddress;
	private Button btnAbsoluteMode;
	private Button btnRelativeDownMode;
	private Button btnRelativeUpMode;
	private int rowIndex;
	private int columnIndex;
	private HexTablePointer newPosition;
		
	public GotoDialog(Shell parent) {
		this(parent, SWT.APPLICATION_MODAL, 0, 0);
	}

	public GotoDialog(Shell parent, int style, int rowIndex, int columnIndex) {
		super(parent, style);
		this.rowIndex = rowIndex;
		this.columnIndex = columnIndex;
	}

	/**
	 * Opens a dialog
	 */
	public HexTablePointer open() {
		dialog = new Shell(getParent(), getStyle());
		GridLayout grid = new GridLayout();
		grid.numColumns = 1;
		dialog.setText("Go to address");
		dialog.setLayout(grid);

		//
		// Panel with user input components
		//
		Composite inputPanel = new Composite(dialog, SWT.NONE);
		GridLayout inputGrid = new GridLayout();
		inputGrid.numColumns = 2;
		inputGrid.marginHeight = 0;
		inputGrid.marginWidth = 0;
		inputGrid.horizontalSpacing = 5;
		inputPanel.setLayout(inputGrid);
		inputPanel.setLayoutData(new GridData(GridData.VERTICAL_ALIGN_FILL));

		//
		// Panel with "Go to" address
		//
		Composite addressPanel = new Composite(inputPanel, SWT.NONE);
		GridLayout addressGrid = new GridLayout();
		addressGrid.numColumns = 1;
		addressPanel.setLayout(addressGrid);
		addressPanel.setLayoutData(new GridData(GridData.VERTICAL_ALIGN_FILL));
		createAddressPanel(addressPanel);
		
		//
		// Panel with "Go to" mode
		//
		Composite modePanel = new Composite(inputPanel, SWT.NONE);
		GridLayout modeGrid = new GridLayout();
		modeGrid.numColumns = 1;
		modePanel.setLayout(modeGrid);
		modePanel.setLayoutData(new GridData(GridData.VERTICAL_ALIGN_FILL));
		createModePanel(modePanel);

		//
		// Panel with dialog buttons
		//
		Composite buttonPanel = new Composite(dialog, SWT.NONE);
		GridLayout buttonGrid = new GridLayout();
		buttonGrid.numColumns = 2;
		buttonPanel.setLayout(buttonGrid);
		buttonPanel.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_END));
		createButtonPanel(buttonPanel);

		dialog.pack();
		dialog.open();
		
		while (!dialog.isDisposed()) {
			if (!getParent().getDisplay().readAndDispatch()) getParent().getDisplay().sleep();
		} // while
		
		return newPosition;
	}

	private void createAddressPanel(Composite parent) {
		Group addressGroup = new Group(parent, SWT.NONE);
		addressGroup.setLayoutData(new GridData(GridData.FILL_VERTICAL));
		addressGroup.setText("Address");
		GridLayout addressLayout = new GridLayout();
		addressLayout.numColumns = 1;
		addressGroup.setLayout(addressLayout);

		btnDecAddress = new Button(addressGroup, SWT.RADIO);
		btnDecAddress.setText("Decimal");
		btnDecAddress.setSelection(true);

		btnHexAddress = new Button(addressGroup, SWT.RADIO);
		btnHexAddress.setText("Hexadecimal");
		btnHexAddress.setSelection(false);

		txtAddress = new Text(addressGroup, SWT.SINGLE | SWT.BORDER);
		txtAddress.setTextLimit(9);
		txtAddress.setText("000000000"); // To make this widget wide enough (see Bug #1277533)
		txtAddress.setFocus();
		
		txtAddress.addFocusListener(new FocusListener() {
			public void focusGained(FocusEvent e) {
				String addr = txtAddress.getText();
				
				if (addr != null && addr.compareTo("000000000") == 0) {
					txtAddress.setText("");
					txtAddress.setTextLimit(8);
				}
			}
			
			public void focusLost(FocusEvent e) {}
		});
	}

	private void createModePanel(Composite parent) {
		Group modeGroup = new Group(parent, SWT.NONE);
		modeGroup.setLayoutData(new GridData(GridData.FILL_VERTICAL));
		modeGroup.setText("Mode");
		GridLayout modeLayout = new GridLayout();
		modeLayout.numColumns = 1;
		modeGroup.setLayout(modeLayout);

		btnAbsoluteMode = new Button(modeGroup, SWT.RADIO);
		btnAbsoluteMode.setText("Absolute");
		btnAbsoluteMode.setSelection(true);

		btnRelativeDownMode = new Button(modeGroup, SWT.RADIO);
		btnRelativeDownMode.setText("Relative down");
		btnRelativeDownMode.setSelection(false);

		btnRelativeUpMode = new Button(modeGroup, SWT.RADIO);
		btnRelativeUpMode.setText("Relative up");
		btnRelativeUpMode.setSelection(false);
	}

	private void createButtonPanel(Composite parent) {
		Button ok = new Button(parent, SWT.PUSH);
		ok.setText("OK");
		GridData data = new GridData();
		data.widthHint = 75;
		ok.setLayoutData(data);
		ok.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent e) {
				calculateNewPosition();
				if (newPosition != null) dialog.dispose();
			}
		});
		
		Button cancel = new Button(parent, SWT.PUSH);
		cancel.setText("Cancel");
		data = new GridData();
		data.widthHint = 75;
		cancel.setLayoutData(data);
		cancel.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent e) {
				dialog.dispose();
			}
		});
	}

	private void calculateNewPosition() {
		//
		// Check the user input
		//
		int iAddress = 0;
		String sAddress = txtAddress.getText();
		boolean addressIsDec = btnDecAddress.getSelection();
		newPosition = null;
		
		if (sAddress.length() == 0) {
			MessageDialog.openError(getParent().getShell(), EHEP.DIALOG_TITLE_ERROR, "Address is missing!");
			txtAddress.setFocus();
			return;
		} // if
		
		try {
			iAddress = Integer.parseInt(sAddress, (addressIsDec) ? 10 : 16);
		}
		catch (NumberFormatException nfeSize) {
			MessageDialog.openError(getParent().getShell(), EHEP.DIALOG_TITLE_ERROR, "Address: Incorrect number format!\nPlease enter a valid " + ((addressIsDec) ? "decimal" : "hexadecimal") + " number.");
			txtAddress.setFocus();
			txtAddress.selectAll();
			return;
		}
				
		if (iAddress < 0) {
			MessageDialog.openError(getParent().getShell(), EHEP.DIALOG_TITLE_ERROR, "Address cannot be negative!");
			txtAddress.setFocus();
			txtAddress.selectAll();
			return;
		} // if

		//
		// Calculate new position (offset)
		//
		if (btnAbsoluteMode.getSelection()) {
			//
			// 'Absolute mode' selected
			//
			newPosition = new HexTablePointer(0, 0).move(iAddress);
		} // if
		else {
			//
			// 'Relative mode' selected
			//
			if (btnRelativeDownMode.getSelection()) {
				newPosition = new HexTablePointer(rowIndex, columnIndex).move(iAddress-1);
			}
			else {
				newPosition = new HexTablePointer(rowIndex, columnIndex).move(-iAddress-1);
			}
		} // else
	}
}
